import * as d3 from 'd3';
import * as topojson from 'topojson-client';
import * as projTools from "@/utils/projection/projectionTools.js";


function containsChineseCharacters(str) {
    // 正则表达式，匹配中文字符
    let regExp = /[\u4e00-\u9fa5]/;
    return regExp.test(str);
}

function clearCanvas(ctx, width, height) {
    ctx.clearRect(0, 0, width, height);
}

let _data = [];

function toPointGeoData(xy, props) {
    return {
        'type': 'Feature',
        'geometry': {
            type: 'Point',
            coordinates: xy
        },
        'properties': props
    }
}

function fromGeoData(d) {
    let coord = d3.geoCentroid(d);
    return toPointGeoData(coord, d.props);
}

function renderText(d, ctx, proj, renderer = false) {
    if (!renderer) {
        _data.push({
            'type': 'text',
            'data': d
        });
    }
    let props = d.props || d.properties || {};
    if (props.text) {
        let coord = d.geometry.coordinates;
        let [x, y] = proj(coord);
        let visible = d3.geoPath().projection(proj)(d);
        // console.log(props.text, coord, x, y, visible);
        if (!visible) {
            return;
        }
        ctx.beginPath();
        ctx.font = `${props['font-size'] || '10px'} Arial`;
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';
        ctx.fillStyle = 'black';
        ctx.fillText(props.text, x, y);
    }
}

function renderPath(d, ctx, path, proj, renderer = false) {
    if (!renderer) {
        _data.push({
            'type': 'path',
            'data': d
        });
    }
    ctx.beginPath();
    path(d);
    let props = d.props || d.properties;
    if (props && props.fill) {
        ctx.fillStyle = props.fill;
        ctx.fill();
    }
    ctx.strokeStyle = props ? props.stroke || 'black' : 'black';
    ctx.lineWidth = props ? props['stroke-width'] || props['line-width'] || '1' : '1';
    ctx.stroke();
}

function reRender(ctx, width, height, path, proj) {
    clearCanvas(ctx, width, height);
    // console.log(_data);
    for (const d of _data) {
        if (d.type === 'path') {
            renderPath(d.data, ctx, path, proj, true);
        } else if (d.type === 'text') {
            renderText(d.data, ctx, proj, true);
        }
    }
}

export async function testProj1(dom) {
    const width = 960;
    const height = Math.min(width, 720);
    const dpr = window.devicePixelRatio ?? 1;
    const zone = d3.select(dom);
    // zone.style('background-color', 'red');
    const canvas = zone.append('canvas')
        .attr("width", dpr * width)
        .attr("height", dpr * height)
        .style("width", `${width}px`)
        .style('background-color', '#c3e8f6')
        .style('display', 'block').style('margin', 'auto');
    let [xc, yc] = projTools.getXyCenter(canvas.node());
    let scale = projTools.getScale(canvas.node(), Math.PI) * 30;
    // console.log(scale);
    let zoomSize = 1;
    let bond = 10;
    const proj = d3.geoOrthographic()
        // .fitExtent([[bond, bond], [width - bond, height - bond]], {type: "Sphere"})
        .reflectX(false)
        .reflectY(false)
        .center([0, 0]) // 地理中心点
        .scale(scale * zoomSize) // 缩放比例
        .translate([xc, yc])
        .rotate([-120.5, -33, 0]);
    // scale = proj.scale();
    // console.log(proj.center(), proj.translate(), proj.rotate(), proj.scale());
    const context = canvas.node().getContext('2d');
    context.scale(dpr, dpr);
    // const path = d3.geoPath(proj);

    const path = d3.geoPath(proj, context);

    clearCanvas(context, width, height);

    let bg = {
        type: 'Sphere',
        props: {
            'fill': '#87ceeb',
            'stroke': 'gray',
            'stroke-width': 0.5
        }
    }

    renderPath(bg, context, path, proj);

    const center = {
        "type": "Feature",
        "geometry": {
            "type": "Point",
            "coordinates": [0, 0],
        },
        "properties": {
            "name": "Points",
            "fill": 'red'
        }
    }

    const holeData = {
        "type": "Feature",
        "geometry": {
            "type": "Polygon",
            "coordinates": [
                [
                    [0, 0],
                    [0, 10],
                    [10, 10],
                    [10, 0],
                    [0, 0]
                ],
                [
                    [5, 5],
                    [5, 3],
                    [7, 3],
                    [7, 5],
                    [5, 5]
                ]
            ]
        },
        "properties": {
            "name": "Hole Polygon",
            "fill": 'yellow',
            'text': 'GO'
        }
    };

    const pointsData = {
        "type": "Feature",
        "geometry": {
            "type": "MultiPoint",
            "coordinates": [
                [0, 85],
                [30, 75],
                [60, 60],
                [90, 45],
                [120, 30],
                [150, 15],
                [180, 0],
                [210, -15],
                [240, -30],
                [270, -45],
                [300, -60],
                [330, -75],
                [360, -85],
            ]
        },
        "properties": {
            "name": "Points",
            "fill": "green"
        }
    }

    const worldData = await d3.json("https://fastly.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json");
    // 将 TopoJSON 对象转换为 GeoJSON 对象
    // console.log(worldData);
    const countries = topojson.feature(worldData, worldData.objects.countries).features;
    // console.log(countries);

    const chData = await d3.json("https://geojson.cn/api/data/100000.json");
    // 将 TopoJSON 对象转换为 GeoJSON 对象
    // console.log(chData);
    const provinces = chData.features;
    console.log(provinces);

    // for (const d of countries) {
    //     d.props = {
    //         'fill': 'lightgray'
    //     }
    //     renderPath(d, context, path, proj);
    // }

    for (const d of provinces) {
        d.props = {
            'text': containsChineseCharacters(d.properties.name) ? d.properties.name : '',
            'fill': 'lightgray',
            'stroke': 'gray',
        }
        renderPath(d, context, path, proj);
        renderText(fromGeoData(d), context, proj);
    }

    renderPath(center, context, path, proj);
    renderPath(holeData, context, path, proj);

    // renderPath(pointsData, context, path, proj);

    const graticule = d3.geoGraticule().step([1, 1]);

    for (const line of graticule.lines()) {
        line.props = {
            'stroke': 'gray',
            'stroke-width': 0.3
        }
        // console.log(line);
        renderPath(line, context, path, proj);
    }


    let drag = d3.drag()
        .on('drag', function (e) {
            // console.log('dragged', e);
            let cr = proj.rotate();
            let ratioX = 45 / scale;
            let ratioY = 45 / scale;
            proj.rotate([cr[0] + e.dx * ratioX / zoomSize, cr[1] - e.dy * ratioY / zoomSize, cr[2]]);
            reRender(context, width, height, path, proj);
        });
    canvas.call(drag);

    let zoom = d3.zoom()
        .scaleExtent([0.1, 5])
        .on('zoom', function (e) {
            // console.log('zoomed', e.transform, e);
            zoomSize = e.transform.k;
            proj.scale(scale * zoomSize);
            reRender(context, width, height, path, proj);
        }).filter(event => event.type === 'wheel'); // 避免点击引起的缩放
    canvas.call(zoom);

}